Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 025890111716e6e5ea1c079fb81ed1786cd6212f


Parents : c90de04
Author : Mark Qvist <bc7291552be7a58f361522990465165c>
Signature : T66BB85Valid, signed by author
Date : 2026-06-07T20:46:10+02:00

Added telephony mic/speaker mute controls

Changes

3 files changed, 92 insertions(+), 1 deletions(-)


Diff

diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index 8010176d..3c8e5f2b 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -2051,6 +2051,10 @@ class SidebandCore():
elif "telephone_get_call_log" in call: connection.send(self.telephone.get_call_log() if self.telephone else [])
elif "telephone_clear_call_log" in call: connection.send(self.telephone.clear_call_log() if self.telephone else False)
elif "telephone_switch_profile" in call: connection.send(self.telephone.switch_profile(call["telephone_switch_profile"]) if self.telephone else False)
+ elif "telephone_mute_mic" in call: connection.send(self.telephone.mute_mic(call["telephone_mute_mic"]) if self.telephone else False)
+ elif "telephone_mute_spk" in call: connection.send(self.telephone.mute_spk(call["telephone_mute_spk"]) if self.telephone else False)
+ elif "telephone_transmit_muted" in call: connection.send(self.telephone.transmit_muted if self.telephone else False)
+ elif "telephone_receive_muted" in call: connection.send(self.telephone.receive_muted if self.telephone else False)
else:
connection.send(None)

diff --git a/sbapp/sideband/voice.py b/sbapp/sideband/voice.py
index 9e39ced0..786292a8 100644
--- a/sbapp/sideband/voice.py
+++ b/sbapp/sideband/voice.py
@@ -77,9 +77,21 @@ class ReticulumTelephone():
self.ringer_device = device
self.telephone.set_ringer(self.ringer_device)
+ def mute_mic(self, muted):
+ self.telephone.mute_transmit(muted)
+
+ def mute_spk(self, muted):
+ self.telephone.mute_receive(muted)
+
def announce(self, attached_interface=None):
self.telephone.announce(attached_interface=attached_interface)
+ @property
+ def receive_muted(self): return self.telephone.receive_muted
+
+ @property
+ def transmit_muted(self): return self.telephone.transmit_muted
+
@property
def is_available(self): return self.state == self.STATE_AVAILABLE
@@ -283,6 +295,14 @@ class ReticulumTelephoneProxy():
@property
def active_profile(self): return self.owner.service_rpc_request({"telephone_active_profile": True })
+ @property
+ def transmit_muted(self):
+ return self.owner.service_rpc_request({"telephone_transmit_muted": True})
+
+ @property
+ def receive_muted(self):
+ return self.owner.service_rpc_request({"telephone_receive_muted": True})
+
def set_busy(self, busy): return self.owner.service_rpc_request({"telephone_set_busy": busy })
def dial(self, dial_target, profile=None): return self.owner.service_rpc_request({"telephone_dial": dial_target, "profile": profile })
def hangup(self): return self.owner.service_rpc_request({"telephone_hangup": True })
@@ -294,4 +314,6 @@ class ReticulumTelephoneProxy():
def announce(self): return self.owner.service_rpc_request({"telephone_announce": True})
def get_call_log(self): return self.owner.service_rpc_request({"telephone_get_call_log": True})
def clear_call_log(self): return self.owner.service_rpc_request({"telephone_clear_call_log": True})
- def switch_profile(self, profile): return self.owner.service_rpc_request({"telephone_switch_profile": profile})
\ No newline at end of file
+ def switch_profile(self, profile): return self.owner.service_rpc_request({"telephone_switch_profile": profile})
+ def mute_mic(self, muted): return self.owner.service_rpc_request({"telephone_mute_mic": muted})
+ def mute_spk(self, muted): return self.owner.service_rpc_request({"telephone_mute_spk": muted})
\ No newline at end of file

diff --git a/sbapp/ui/voice.py b/sbapp/ui/voice.py
index b54fb109..2963c4f7 100644
--- a/sbapp/ui/voice.py
+++ b/sbapp/ui/voice.py
@@ -74,6 +74,8 @@ class Voice():
rb = self.screen.ids.reject_button
ih = self.screen.ids.identity_hash
pb = self.screen.ids.call_profile_button
+ rm = self.screen.ids.spk_mute_button
+ tm = self.screen.ids.mic_mute_button
if self.app.sideband.voice_running:
telephone = self.app.sideband.telephone
if self.path_requesting:
@@ -112,6 +114,27 @@ class Voice():
if telephone.caller: ih.text = RNS.hexrep(telephone.caller.hash, delimit=False)
if telephone.active_profile: self.call_profile = telephone.active_profile
+ if telephone.is_in_call:
+ rm.disabled = False
+ tm.disabled = False
+ else:
+ rm.disabled = True
+ tm.disabled = True
+
+ if telephone.receive_muted:
+ rm.text = "Output Muted"
+ rm.icon = "volume-off"
+ else:
+ rm.text = "Output Active"
+ rm.icon = "volume-high"
+
+ if telephone.transmit_muted:
+ tm.text = "Mic Muted"
+ tm.icon = "microphone-off"
+ else:
+ tm.text = "Mic Active"
+ tm.icon = "microphone"
+
if self.app.sideband.getstate("voice.connection_failure"):
self.app.sideband.setstate("voice.connection_failure", False)
toast("Could not connect call", duration=5)
@@ -251,6 +274,18 @@ class Voice():
self.initial_call_profile = None
+ def mic_mute_action(self, sender=None):
+ if self.app.sideband.voice_running:
+ if self.app.sideband.telephone.transmit_muted: self.app.sideband.telephone.mute_mic(False)
+ else: self.app.sideband.telephone.mute_mic(True)
+ self.update_call_status()
+
+ def spk_mute_action(self, sender=None):
+ if self.app.sideband.voice_running:
+ if self.app.sideband.telephone.receive_muted: self.app.sideband.telephone.mute_spk(False)
+ else: self.app.sideband.telephone.mute_spk(True)
+ self.update_call_status()
+
### Settings screen
######################################
@@ -595,6 +630,7 @@ MDScreen:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
+ spacing: "24dp"
padding: [dp(28), dp(24), dp(28), dp(24)]
MDRectangleFlatIconButton:
@@ -606,6 +642,35 @@ MDScreen:
font_size: dp(16)
size_hint: [1.0, None]
on_release: root.delegate.clear_log_action(self)
+
+ MDBoxLayout:
+ orientation: "horizontal"
+ spacing: "24dp"
+ size_hint_y: None
+ height: self.minimum_height
+ padding: [dp(0), dp(0), dp(0), dp(0)]
+
+ MDRectangleFlatIconButton:
+ id: mic_mute_button
+ icon: "microphone"
+ text: "Mic Active"
+ padding: [dp(0), dp(14), dp(0), dp(14)]
+ icon_size: dp(24)
+ font_size: dp(16)
+ size_hint: [1.0, None]
+ on_release: root.delegate.mic_mute_action(self)
+ disabled: False
+
+ MDRectangleFlatIconButton:
+ id: spk_mute_button
+ icon: "volume-high"
+ text: "Output Active"
+ padding: [dp(0), dp(14), dp(0), dp(14)]
+ icon_size: dp(24)
+ font_size: dp(16)
+ size_hint: [1.0, None]
+ on_release: root.delegate.spk_mute_action(self)
+ disabled: False
"""
layout_voice_settings_screen = """


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────